<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring Boot内嵌服务器深度解析 | 技术小馆</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.7;
        }
        h1, h2, h3, h4, h5, h6 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: #2d3748;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background: #f8f9fa;
            border-left: 4px solid #667eea;
            font-family: 'Courier New', monospace;
        }
        .card-hover {
            transition: all 0.3s ease;
        }
        .card-hover:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .highlight {
            position: relative;
        }
        .highlight:before {
            content: "";
            position: absolute;
            left: 0;
            bottom: 2px;
            width: 100%;
            height: 8px;
            background: rgba(102, 126, 234, 0.2);
            z-index: -1;
            transition: all 0.3s ease;
        }
        .highlight:hover:before {
            height: 14px;
            background: rgba(102, 126, 234, 0.3);
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <div class="hero-gradient text-white py-20 px-4">
        <div class="max-w-5xl mx-auto text-center">
            <h1 class="text-5xl font-bold mb-6">Spring Boot内嵌服务器深度解析</h1>
            <p class="text-xl opacity-90 mb-8">从传统部署到现代化应用的演进之路</p>
            <div class="flex justify-center space-x-4">
                <div class="bg-white bg-opacity-20 px-6 py-3 rounded-full flex items-center">
                    <i class="fas fa-server mr-2"></i>
                    <span>内嵌服务器原理</span>
                </div>
                <div class="bg-white bg-opacity-20 px-6 py-3 rounded-full flex items-center">
                    <i class="fas fa-code mr-2"></i>
                    <span>源码级解析</span>
                </div>
                <div class="bg-white bg-opacity-20 px-6 py-3 rounded-full flex items-center">
                    <i class="fas fa-rocket mr-2"></i>
                    <span>性能优化</span>
                </div>
            </div>
        </div>
    </div>

    <!-- Main Content -->
    <div class="max-w-5xl mx-auto px-4 py-16">
        <!-- Introduction -->
        <div class="mb-16">
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 card-hover">
                <div class="p-8">
                    <h2 class="text-3xl font-bold mb-6 text-gray-800">传统部署 vs 内嵌服务器</h2>
                    <p class="text-lg text-gray-700 mb-6">在传统的 Java Web 开发中，Web 应用通常部署在外部的容器（如 Tomcat、Jetty 或 Undertow）中。但在 Spring Boot 中，Web 服务器被集成到应用中，成为内嵌服务器，直接在 Spring Boot 应用启动时启动。这种方式可以简化开发和部署过程，减少了开发人员的运维成本。</p>
                    <div class="bg-gray-100 p-6 rounded-lg">
                        <div class="flex items-center mb-4">
                            <div class="bg-blue-500 w-8 h-8 rounded-full flex items-center justify-center text-white mr-4">
                                <i class="fas fa-check"></i>
                            </div>
                            <h3 class="text-xl font-semibold text-gray-800">关键优势</h3>
                        </div>
                        <div class="grid md:grid-cols-3 gap-4">
                            <div class="bg-white p-4 rounded-lg shadow-sm">
                                <div class="text-blue-500 mb-2">
                                    <i class="fas fa-box-open text-2xl"></i>
                                </div>
                                <h4 class="font-medium mb-1">简化部署</h4>
                                <p class="text-sm text-gray-600">单个可执行JAR包包含所有依赖</p>
                            </div>
                            <div class="bg-white p-4 rounded-lg shadow-sm">
                                <div class="text-blue-500 mb-2">
                                    <i class="fas fa-sliders-h text-2xl"></i>
                                </div>
                                <h4 class="font-medium mb-1">灵活配置</h4>
                                <p class="text-sm text-gray-600">支持多种服务器和自定义设置</p>
                            </div>
                            <div class="bg-white p-4 rounded-lg shadow-sm">
                                <div class="text-blue-500 mb-2">
                                    <i class="fas fa-robot text-2xl"></i>
                                </div>
                                <h4 class="font-medium mb-1">自动化管理</h4>
                                <p class="text-sm text-gray-600">自动配置减少手动工作</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 1 -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <span class="mr-4">1.</span>
                <span class="highlight">Spring Boot 内嵌服务器的核心类</span>
            </h2>
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 card-hover">
                <div class="p-8">
                    <p class="text-gray-700 mb-6">Spring Boot 支持的内嵌服务器有多个：Tomcat、Jetty 和 Undertow。<code class="bg-gray-100 px-2 py-1 rounded">SpringApplication</code> 类通过 <code class="bg-gray-100 px-2 py-1 rounded">EmbeddedWebApplicationContext</code> 启动和配置内嵌服务器。内嵌服务器的配置和启动通常是在 Spring Boot 的自动配置机制下进行的，主要通过 <code class="bg-gray-100 px-2 py-1 rounded">SpringBootServletInitializer</code> 和 <code class="bg-gray-100 px-2 py-1 rounded">EmbeddedServletContainerFactory</code> 相关类来完成。</p>
                    
                    <h3 class="text-2xl font-semibold mb-4 mt-8 flex items-center">
                        <i class="fas fa-play-circle text-blue-500 mr-3"></i>
                        <span>SpringApplication 启动时选择内嵌服务器</span>
                    </h3>
                    <p class="text-gray-700 mb-4"><code class="bg-gray-100 px-2 py-1 rounded">SpringApplication</code> 是 Spring Boot 启动的核心类，它负责创建应用上下文、启动嵌入式 Web 服务器以及执行自动配置。通过 <code class="bg-gray-100 px-2 py-1 rounded">run()</code> 方法启动时，<code class="bg-gray-100 px-2 py-1 rounded">SpringApplication</code> 会自动判断应该使用哪个内嵌服务器。以下是相关的代码片段：</p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm">public ConfigurableApplicationContext run(String... args) {
    // ... 省略其他代码
    // 判断 WebApplicationType 类型，决定是否需要启动内嵌服务器
    if (this.webApplicationType == WebApplicationType.SERVLET) {
        // Web应用类型为SERVLET，启动内嵌服务器
        return runWebApplication(args);
    }
    // ... 省略其他代码
}</code></pre>
                    </div>
                    
                    <p class="text-gray-700 mb-6">在 <code class="bg-gray-100 px-2 py-1 rounded">run()</code> 方法中，<code class="bg-gray-100 px-2 py-1 rounded">this.webApplicationType</code> 被设置为 <code class="bg-gray-100 px-2 py-1 rounded">WebApplicationType.SERVLET</code>，表示当前应用为 Servlet 类型的 Web 应用，Spring Boot 会根据此类型决定是否启动内嵌服务器。</p>
                    
                    <h3 class="text-2xl font-semibold mb-4 mt-8 flex items-center">
                        <i class="fas fa-code-branch text-blue-500 mr-3"></i>
                        <span>选择内嵌服务器的条件判断</span>
                    </h3>
                    <p class="text-gray-700 mb-4">Spring Boot 使用 <code class="bg-gray-100 px-2 py-1 rounded">WebApplicationType</code> 枚举来判断应用类型。其主要有三种类型：</p>
                    
                    <div class="grid md:grid-cols-3 gap-6 mb-6">
                        <div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
                            <h4 class="font-bold text-blue-700 mb-2 flex items-center">
                                <i class="fas fa-times-circle mr-2"></i>
                                NONE
                            </h4>
                            <p class="text-sm text-gray-700">非 Web 应用，不启动内嵌服务器。</p>
                        </div>
                        <div class="bg-green-50 p-4 rounded-lg border border-green-100">
                            <h4 class="font-bold text-green-700 mb-2 flex items-center">
                                <i class="fas fa-server mr-2"></i>
                                SERVLET
                            </h4>
                            <p class="text-sm text-gray-700">Servlet 类型的 Web 应用，启动嵌入式 Tomcat、Jetty 或 Undertow。</p>
                        </div>
                        <div class="bg-purple-50 p-4 rounded-lg border border-purple-100">
                            <h4 class="font-bold text-purple-700 mb-2 flex items-center">
                                <i class="fas fa-bolt mr-2"></i>
                                REACTIVE
                            </h4>
                            <p class="text-sm text-gray-700">响应式 Web 应用，启动嵌入式 WebFlux 服务（例如 Undertow 或 Netty）。</p>
                        </div>
                    </div>
                    
                    <p class="text-gray-700">根据不同的 Web 应用类型，Spring Boot 会选择合适的内嵌服务器进行启动。</p>
                </div>
            </div>
        </div>

        <!-- Section 2 -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <span class="mr-4">2.</span>
                <span class="highlight">内嵌 Tomcat 服务器的自动配置</span>
            </h2>
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 card-hover">
                <div class="p-8">
                    <p class="text-gray-700 mb-6">Tomcat 是 Spring Boot 默认的内嵌 Web 服务器。Spring Boot 通过 <code class="bg-gray-100 px-2 py-1 rounded">TomcatServletWebServerFactory</code> 类配置并启动 Tomcat 服务器。我们来详细看一下 Tomcat 相关的源码。</p>
                    
                    <h3 class="text-2xl font-semibold mb-4 mt-8 flex items-center">
                        <i class="fab fa-java text-blue-500 mr-3"></i>
                        <span>TomcatServletWebServerFactory</span>
                    </h3>
                    <p class="text-gray-700 mb-4"><code class="bg-gray-100 px-2 py-1 rounded">TomcatServletWebServerFactory</code> 是 Tomcat 内嵌服务器的工厂类。它实现了 <code class="bg-gray-100 px-2 py-1 rounded">EmbeddedServletContainerFactory</code> 接口，用于创建和配置 Tomcat 实例。</p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm">public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory {
    @Override
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat tomcat = createTomcatServer();
        // 配置服务器
        configureHost(tomcat);
        configureEngine(tomcat);
        // 启动服务器
        tomcat.start();
        return new TomcatWebServer(tomcat, this.getSslStoreProvider());
    }

    private Tomcat createTomcatServer() {
        // 创建 Tomcat 实例
        Tomcat tomcat = new Tomcat();
        tomcat.setBaseDir(this.baseDirectory.getAbsolutePath());
        return tomcat;
    }
}</code></pre>
                    </div>
                    
                    <div class="grid md:grid-cols-2 gap-6 mb-6">
                        <div>
                            <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                                <i class="fas fa-cog text-blue-500 mr-2"></i>
                                getWebServer() 方法
                            </h4>
                            <p class="text-sm text-gray-700">这是 <code class="bg-gray-100 px-1 py-0.5 rounded">TomcatServletWebServerFactory</code> 类的核心方法，用于创建并启动 Tomcat 服务器。在此方法中，<code class="bg-gray-100 px-1 py-0.5 rounded">createTomcatServer()</code> 用于创建一个 Tomcat 实例，并配置基本的服务器信息。</p>
                        </div>
                        <div>
                            <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                                <i class="fas fa-server text-blue-500 mr-2"></i>
                                TomcatWebServer
                            </h4>
                            <p class="text-sm text-gray-700">该类是 Tomcat 服务器的封装，它实现了 <code class="bg-gray-100 px-1 py-0.5 rounded">WebServer</code> 接口，用于控制 Tomcat 的生命周期以及与 Spring Boot 应用上下文的整合。</p>
                        </div>
                    </div>
                    
                    <h3 class="text-2xl font-semibold mb-4 mt-8 flex items-center">
                        <i class="fas fa-power-off text-blue-500 mr-3"></i>
                        <span>Tomcat 的启动</span>
                    </h3>
                    <p class="text-gray-700">当 <code class="bg-gray-100 px-2 py-1 rounded">TomcatServletWebServerFactory</code> 创建并配置完 Tomcat 实例后，Tomcat 会通过 <code class="bg-gray-100 px-2 py-1 rounded">tomcat.start()</code> 启动。此时，Spring Boot 应用的 Web 环境已经建立，Tomcat 服务器开始监听端口，处理 HTTP 请求。</p>
                </div>
            </div>
        </div>

        <!-- Section 3 -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <span class="mr-4">3.</span>
                <span class="highlight">Jetty 和 Undertow 的内嵌支持</span>
            </h2>
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 card-hover">
                <div class="p-8">
                    <p class="text-gray-700 mb-6">除了 Tomcat，Spring Boot 还支持 Jetty 和 Undertow。其配置和启动过程与 Tomcat 类似，下面是 <code class="bg-gray-100 px-2 py-1 rounded">Jetty</code> 和 <code class="bg-gray-100 px-2 py-1 rounded">Undertow</code> 的启动逻辑：</p>
                    
                    <div class="grid md:grid-cols-2 gap-8">
                        <div>
                            <h3 class="text-2xl font-semibold mb-4 flex items-center">
                                <i class="fab fa-java text-red-500 mr-3"></i>
                                <span>JettyWebServerFactory</span>
                            </h3>
                            <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                                <pre><code class="text-sm">public class JettyWebServerFactory extends AbstractServletWebServerFactory {
    @Override
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Server jetty = new Server(this.port);
        // 配置 Jetty
        configureServer(jetty);
        jetty.start();
        return new JettyWebServer(jetty);
    }
}</code></pre>
                            </div>
                            <p class="text-gray-700"><code class="bg-gray-100 px-2 py-1 rounded">JettyWebServerFactory</code> 类与 <code class="bg-gray-100 px-2 py-1 rounded">TomcatServletWebServerFactory</code> 类类似，创建 Jetty 实例并启动它。</p>
                        </div>
                        <div>
                            <h3 class="text-2xl font-semibold mb-4 flex items-center">
                                <i class="fab fa-java text-indigo-500 mr-3"></i>
                                <span>UndertowWebServerFactory</span>
                            </h3>
                            <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                                <pre><code class="text-sm">public class UndertowWebServerFactory extends AbstractServletWebServerFactory {
    @Override
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Undertow undertow = Undertow.builder()
                .addHttpListener(this.port, this.address)
                .setHandler(new HttpHandler() {
                    // 配置 handler
                })
                .build();
        undertow.start();
        return new UndertowWebServer(undertow);
    }
}</code></pre>
                            </div>
                            <p class="text-gray-700"><code class="bg-gray-100 px-2 py-1 rounded">UndertowWebServerFactory</code> 使用 Undertow 创建并启动 Web 服务器。与 Jetty 和 Tomcat 不同，Undertow 更加轻量，适合对性能要求较高的应用。</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 4 -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <span class="mr-4">4.</span>
                <span class="highlight">Web 服务器的自动配置</span>
            </h2>
            <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8 card-hover">
                <div class="p-8">
                    <p class="text-gray-700 mb-6">Spring Boot 的 <code class="bg-gray-100 px-2 py-1 rounded">WebServerFactoryAutoConfiguration</code> 类通过条件注解（如 <code class="bg-gray-100 px-2 py-1 rounded">@ConditionalOnClass</code> 和 <code class="bg-gray-100 px-2 py-1 rounded">@ConditionalOnMissingBean</code>）自动配置 Web 服务器。</p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm">@Configuration
@ConditionalOnClass(WebServer.class)
@ConditionalOnMissingBean(WebServerFactory.class)
public class WebServerFactoryAutoConfiguration {

    @Bean
    public WebServerFactory webServerFactory() {
        return new TomcatServletWebServerFactory();
    }
}</code></pre>
                    </div>
                    
                    <div class="grid md:grid-cols-2 gap-6">
                        <div>
                            <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                                <i class="fas fa-filter text-blue-500 mr-2"></i>
                                条件化配置
                            </h4>
                            <p class="text-sm text-gray-700"><code class="bg-gray-100 px-1 py-0.5 rounded">@ConditionalOnClass(WebServer.class)</code> 确保只有在类路径中存在 WebServer 类时才会自动配置 Web 服务器。</p>
                        </div>
                        <div>
                            <h4 class="font-bold text-gray-800 mb-2 flex items-center">
                                <i class="fas fa-search-minus text-blue-500 mr-2"></i>
                                缺失 Bean 的配置
                            </h4>
                            <p class="text-sm text-gray-700"><code class="bg-gray-100 px-1 py-0.5 rounded">@ConditionalOnMissingBean(WebServerFactory.class)</code> 表示如果容器中没有 <code class="bg-gray-100 px-1 py-0.5 rounded">WebServerFactory</code> 类型的 Bean 时，Spring Boot 会自动创建一个默认的 <code class="bg-gray-100 px-1 py-0.5 rounded">TomcatServletWebServerFactory</code> 实例。</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Conclusion -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <span class="mr-4">5.</span>
                <span class="highlight">Spring Boot 内嵌服务器的优点与总结</span>
            </h2>
            <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                <div class="p-8">
                    <div class="grid md:grid-cols-3 gap-6 mb-8">
                        <div class="bg-blue-50 p-6 rounded-lg border border-blue-200">
                            <div class="text-blue-500 text-3xl mb-4">
                                <i class="fas fa-box"></i>
                            </div>
                            <h3 class="text-xl font-semibold mb-2">简化部署</h3>
                            <p class="text-gray-700">内嵌服务器使得开发者不再需要单独配置外部 Web 服务器（如 Tomcat），而是将服务器与应用打包成一个独立的可执行 JAR 文件，简化了部署过程。</p>
                        </div>
                        <div class="bg-green-50 p-6 rounded-lg border border-green-200">
                            <div class="text-green-500 text-3xl mb-4">
                                <i class="fas fa-sliders-h"></i>
                            </div>
                            <h3 class="text-xl font-semibold mb-2">灵活配置</h3>
                            <p class="text-gray-700">Spring Boot 提供了内嵌服务器的全面支持，并允许开发者选择不同的服务器（Tomcat、Jetty、Undertow），还可以通过配置文件进行灵活的自定义设置。</p>
                        </div>
                        <div class="bg-purple-50 p-6 rounded-lg border border-purple-200">
                            <div class="text-purple-500 text-3xl mb-4">
                                <i class="fas fa-robot"></i>
                            </div>
                            <h3 class="text-xl font-semibold mb-2">自动化管理</h3>
                            <p class="text-gray-700">Spring Boot 的自动配置机制使得内嵌服务器的配置和启动过程对开发者透明，大大减少了繁琐的配置。</p>
                        </div>
                    </div>
                    
                    <div class="bg-gray-100 p-6 rounded-lg">
                        <h3 class="text-xl font-semibold mb-4 flex items-center">
                            <i class="fas fa-lightbulb text-yellow-500 mr-3"></i>
                            <span>技术要点总结</span>
                        </h3>
                        <ul class="space-y-3">
                            <li class="flex items-start">
                                <div class="bg-blue-100 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">
                                    <i class="fas fa-check text-blue-500 text-xs"></i>
                                </div>
                                <span class="text-gray-700">Spring Boot 支持三种内嵌服务器：Tomcat(默认)、Jetty 和 Undertow</span>
                            </li>
                            <li class="flex items-start">
                                <div class="bg-blue-100 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">
                                    <i class="fas fa-check text-blue-500 text-xs"></i>
                                </div>
                                <span class="text-gray-700">通过 <code class="bg-gray-200 px-1 py-0.5 rounded">WebApplicationType</code> 判断应用类型并选择相应的服务器</span>
                            </li>
                            <li class="flex items-start">
                                <div class="bg-blue-100 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">
                                    <i class="fas fa-check text-blue-500 text-xs"></i>
                                </div>
                                <span class="text-gray-700">自动配置通过 <code class="bg-gray-200 px-1 py-0.5 rounded">@ConditionalOnClass</code> 和 <code class="bg-gray-200 px-1 py-0.5 rounded">@ConditionalOnMissingBean</code> 实现</span>
                            </li>
                            <li class="flex items-start">
                                <div class="bg-blue-100 rounded-full w-6 h-6 flex items-center justify-center mr-3 mt-1 flex-shrink-0">
                                    <i class="fas fa-check text-blue-500 text-xs"></i>
                                </div>
                                <span class="text-gray-700">内嵌服务器显著简化了部署流程，提升了开发效率</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>

        <!-- Footer -->
        <footer class="bg-gray-900 text-white py-12 px-4">
            <div class="max-w-5xl mx-auto">
                <div class="flex flex-col md:flex-row justify-between items-center">
                    <div class="mb-6 md:mb-0">
                        <h3 class="text-2xl font-bold mb-2">技术小馆</h3>
                        <p class="text-gray-400">深入技术细节，探寻架构之美</p>
                    </div>
                    <div>
                        <a href="http://www.yuque.com/jtostring" class="text-gray-300 hover:text-white transition duration-300 flex items-center">
                            <i class="fas fa-external-link-alt mr-2"></i>
                            <span>访问语雀主页</span>
                        </a>
                    </div>
                </div>
                <div class="border-t border-gray-800 mt-8 pt-8 text-center text-gray-500 text-sm">
                    &copy; 2023 技术小馆. 保留所有权利.
                </div>
            </div>
        </footer>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: false
            }
        });
    </script>
</body>
</html>